package com.wtwd.campus.aspect;

import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.common.RespCode;
import com.wtwd.campus.common.RespCodeEntity;
import com.wtwd.campus.common.RespEntity;
import com.wtwd.campus.entity.AuditLog;
import com.wtwd.campus.model.vo.ResultVO;
import com.wtwd.campus.service.LogService;
import com.wtwd.campus.service.RedisService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

@Component
@Aspect
public class AuditLogAspect {
    private final static Logger logger = LoggerFactory.getLogger(AuditLogAspect.class);

    @Autowired
    private RedisService redisService;
    @Autowired
    private LogService logService;

    @Around("@annotation(com.wtwd.campus.annotation.AuditLog)")
    public Object addLog(ProceedingJoinPoint pjp) {
        System.out.println("开始时间：" + System.currentTimeMillis());
        logger.info("环绕通知开始 aroundAdvice : ProceedingJoinPoint = " + pjp);
        //判断token是否过期
        Object rtValue = null;
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader(Constants.HEADER_TOKEN_KEY);
        //获取用户的id
        Map<String, Object> msg = redisService.getUserInfoByToken(token);
        String userMsg = (String)msg.get("user");
        JSONObject jsonObject = JSONObject.parseObject(userMsg);
        Integer userId =(Integer)jsonObject.get("userId");
        if (userId == null) {//token过期
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        //构建一个日志存储对象
        AuditLog audit = new AuditLog();
        // 获取方法上面的注解
        com.wtwd.campus.annotation.AuditLog auditLog = getControllerAnnotation(pjp);
        // 获取操作描述的属性值
        String operation = auditLog.operationType();//获取操作类型
        try {
            logger.info("logger类中的开始记录日志....前置");
            rtValue = pjp.proceed();
            logger.info("logger类中的开始记录日志....后置");
            return rtValue;
        } catch (Throwable throwable) {
            logger.info("logger类中的开始记录日志....异常");
            throwable.printStackTrace();
        } finally {
            //在执行完成之后记录操作日志
            String operationContent = auditLog.operationContent();
            //获取操作的学校的id
            String orgCode = auditLog.orgCode();
            audit.setOperation_content(operationContent);//记录操作描述
            audit.setOperation(operation);//记录操作类型
            audit.setOperation_user(userId);//记录审核用户
            audit.setOperation_time(new Date().getTime());//记录操作时间
            audit.setOrg_code(orgCode);//操作所对应的组织的code
            //根据方法的执行结果，保存到数据库中
            boolean flag=false;
            if (rtValue instanceof RespEntity ) {
                if (((RespEntity) rtValue).getCode() == RespCode.SUCCESS.getCode()) {//操作成功才会去记录它
                    flag=true;
                }
            }
            if (rtValue instanceof RespCodeEntity ) {
                if (((RespCodeEntity) rtValue).getCode() == RespCode.SUCCESS.getCode()) {//操作成功才会去记录它
                    flag=true;
                }
            }
            if(rtValue instanceof ResultVO){
                if (((ResultVO) rtValue).getCode() == RespCode.SUCCESS.getCode()) {
                    flag=true;
                }
            }
            if(flag){
                logger.info(" 记录操作日志 : RespEntity = " + rtValue);
                int i = logService.addAuditLog(audit);
            }
            logger.info(" 记录操作日志  最终返回结果 " + rtValue);
            System.out.println("结束时间：" + System.currentTimeMillis());
            return rtValue;
        }
    }


    /**
     * 获取注解中对方法的描述信息 （获取注解对象）
     *
     * @param joinPoint 切点
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static com.wtwd.campus.annotation.AuditLog getControllerAnnotation(JoinPoint joinPoint) {
        String targetName;
        String methodName = null;
        Object[] arguments = null;
        Class targetClass;
        Method[] methods = null;
        com.wtwd.campus.annotation.AuditLog logAnnotation = null;
        try {
            targetName = joinPoint.getTarget().getClass().getName();
            methodName = joinPoint.getSignature().getName();
            arguments = joinPoint.getArgs();
            targetClass = Class.forName(targetName);
            methods = targetClass.getMethods();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    logAnnotation = method.getAnnotation(com.wtwd.campus.annotation.AuditLog.class);
                    break;
                }
            }
        }
        return logAnnotation;
    }

}
